﻿using SLUISystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

namespace SLBehaviourSystem
{
    public class BehaviourEditorNode : EditorDragableItem
    {
        public static int IdIndex;
        public static BehaviourEditorNode Create(BehaviourWindow window, BehaviourTreeJsonData jsonData)
        {

            Dictionary<int, BehaviourTreeNodeJsonData> dataCache = new Dictionary<int, BehaviourTreeNodeJsonData>();

            Dictionary<int, BehaviourEditorNode> nodeCache = new Dictionary<int, BehaviourEditorNode>();

            for (int i = jsonData.Nodes.Count - 1; i >= 0; i--)
            {
                BehaviourEditorNode node = new BehaviourEditorNode();
                node.Window = window;
                dataCache.Add(jsonData.Nodes[i].Id, jsonData.Nodes[i]);
                nodeCache.Add(jsonData.Nodes[i].Id, node);
                List<int> ChildIds = jsonData.Nodes[i].ChildIds;
                node.Data = jsonData.Nodes[i];
                node.Childs = new List<BehaviourEditorNode>();
                node.SetPosition(jsonData.Nodes[i].Position);
                if (ChildIds.Count > 0)
                {
                    for (int j = 0; j < ChildIds.Count; j++)
                    {
                        if (nodeCache.ContainsKey(ChildIds[j]))
                        {
                            BehaviourEditorNode childNode = nodeCache[ChildIds[j]];
                            childNode.Parent = node;
                            node.Childs.Add(childNode);
                        }
                        else
                        {
                            DebugUtils.LogError("缓存中不包含节点id为"+ChildIds[j]+"的节点");
                        }

                    }
                }
                node.CheckLayout();
            }
            return nodeCache[0];
        }

        public BehaviourEditorNode Parent;

        public BehaviourTreeNodeJsonData Data;

        public List<BehaviourEditorNode> Childs;

        public BehaviourWindow Window;

        public float NeedWidth = 0;

        public BehaviourEditorNode()
        {
            Childs = new List<BehaviourEditorNode>();
        }

        public void Save(BehaviourTreeJsonData json)
        {
            Data.Position = rectInScroll.position;
            json.Nodes.Add(Data);
            Data.ChildIds.Clear();
            for (int i = 0; i < Childs.Count; i++)
            {
                Data.ChildIds.Add(Childs[i].Data.Id);
                Childs[i].Save(json);
            }
        }

        public bool CheckDrag(BehaviourEditorNode selectedNode,Vector2 clickPos, Vector2 moveDelta)
        {
            if (selectedNode.Data.Id == Data.Id) 
            {
                SetPosition(rectInScroll.position + moveDelta);
                return true;
            }
            for (int i = 0; i < Childs.Count; i++)
            {
                if (Childs[i].CheckDrag(selectedNode, clickPos, moveDelta))
                {
                    return true;
                }
            }
            return false;
        }

        public int CheckPredictNode(out BehaviourEditorNode predictParent)
        {
            predictParent = null;
            if (CheckInChildArea())
            {
                predictParent = this;
                int index = CheckInChildIndex();
                Debug.Log(Data.Id + " " + index);
                return index;
            }
            else
            {
                for (int i = 0; i < Childs.Count; i++)
                {
                    int index = Childs[i].CheckPredictNode(out predictParent);
                    if (index!=-1)
                    {
                        return index;
                    }
                }
            }
            return -1;
        }

        private bool CheckInChildArea()
        {
            if (Window.CurSelectNode != null && Window.CurSelectNode!=this)
            {
                float childWidth = NeedWidth + rectInGraph.width + BehaciourEditorDefines.InteralX;
                float childHeight = rectInGraph.height + BehaciourEditorDefines.InteralY;

                bool isInHeight = Mathf.Abs(rectInScroll.y - Window.CurSelectNode.rectInScroll.y) < childHeight;
                bool isInWidth = Mathf.Abs(rectInScroll.x - Window.CurSelectNode.rectInScroll.x) < childWidth / 2;
                return isInHeight && isInWidth;
                //Window.CurSelectNode.rectInScroll
            }
            else
            {
                return false;
            }
        }

        private int CheckInChildIndex()
        {
            if (Window.CurSelectNode != null)
            {
                float width = rectInScroll.x-NeedWidth/2 + BehaciourEditorDefines.InteralX;
                for (int i = 0; i < Childs.Count+1; i++)
                {
                    width += rectInGraph.width + BehaciourEditorDefines.InteralX;
                    if (width > Window.CurSelectNode.rectInScroll.x)
                    {
                        return i;
                    }
                }
            }
            return 0;
        }

        public BehaviourEditorNode CheckClickAndChild(Vector2 clickPos)
        {
            CheckClick(clickPos);
            if (IsClicking)
            {
                return this;
            }
            for (int i = 0; i < Childs.Count; i++)
            {
                BehaviourEditorNode node = Childs[i].CheckClickAndChild(clickPos);
                if (node != null)
                {
                    return node;
                }
            }
            return null;
        }

        public void CheckLayout()
        {
            NeedWidth = 0;
            if (Childs.Count > 0)
            {
                for (int i = 0; i < Childs.Count; i++)
                {
                    NeedWidth += Childs[i].NeedWidth;
                }
            }
            else
            {
                NeedWidth = rectInGraph.width + 2 * BehaciourEditorDefines.InteralX;
            }
        }

        public void ReLayout()
        {
            CheckLayout();
            float tempWidth = 0;
            
            for (int i = 0; i < Childs.Count; i++)
            {
                Vector2 position = new Vector2(this.position.x - NeedWidth / 2 + Childs[i].NeedWidth / 2 + tempWidth,
                    this.position.y + rectInGraph.height + BehaciourEditorDefines.InteralY);
                tempWidth += Childs[i].NeedWidth;
                Childs[i].SetPosition(position);
                Childs[i].ReLayout();
            }
        }

        public void ReCode()
        {
            Data.Id = IdIndex++;
            for (int i = 0; i < Childs.Count; i++)
            {
                Childs[i].ReCode();
            }
            Data.ChildIds.Clear();
            for (int i = 0; i < Childs.Count; i++)
            {
                Data.ChildIds.Add(Childs[i].Data.Id);
            }
        }
    }
}
